package com.wei.czz.framework.common.manager;

import com.alibaba.fastjson2.JSON;
import com.wei.czz.common.constant.EntityConstant;
import com.wei.czz.common.constant.RedisConstant;
import com.wei.czz.common.dto.common.messageFlow.MessageFlowDto;
import com.wei.czz.common.dto.common.messageFlow.MessageFlowEnumDto;
import com.wei.czz.common.dto.common.messageFlow.MessageFlowRetryDto;
import com.wei.czz.common.enums.ResultEnum;
import com.wei.czz.common.enums.common.messageFlow.MessageStatusEnum;
import com.wei.czz.common.enums.rabbitMQ.MqEnum;
import com.wei.czz.common.exception.CzzException;
import com.wei.czz.common.po.UserPo;
import com.wei.czz.common.tool.PageDto;
import com.wei.czz.common.utils.CacheKeyUtils;
import com.wei.czz.common.utils.CopyUtils;
import com.wei.czz.common.utils.SecurityUtils;
import com.wei.czz.common.utils.TimeUtils;
import com.wei.czz.framework.common.handler.redis.RedisHandler;
import com.wei.czz.framework.common.handler.redis.RedisStringHandler;
import com.wei.czz.common.vo.common.messageFlow.MessageFlowFormVo;
import com.wei.czz.framework.common.entity.MessageFlowEntity;
import com.wei.czz.framework.common.helper.CacheHelper;
import com.wei.czz.framework.common.helper.RabbitHelper;
import com.wei.czz.framework.common.service.AesService;
import com.wei.czz.framework.common.service.MessageFlowService;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
import java.util.function.Function;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wyw
 * date: 2024-05-29 14:16:17
 * className: MessageFlowManager mq消息发送记录管理类
 * version: 1.0
 * description:
 */
@Component
@AllArgsConstructor
public class MessageFlowManager {

    private static final Logger log = LoggerFactory.getLogger(MessageFlowManager.class);

    private static final String SEND = "send-";

    private final MessageFlowService messageFlowService;

    private final AesService aesService;

    private final CacheHelper cacheHelper;

    private final RabbitHelper rabbitHelper;

    private final RedisStringHandler redisStringHandler;

    private final RedisHandler redisHandler;

    public PageDto<MessageFlowDto> getMessageFlowPageList(MessageFlowFormVo messageFlowFormVo) {
        // 获取请求用户
        Long optUserId = SecurityUtils.getUserId();

        if (Objects.nonNull(messageFlowFormVo.getEndCreateTime())) {
            messageFlowFormVo.setEndCreateTime(TimeUtils.getEndDate(messageFlowFormVo.getEndCreateTime()));
        }

        /*
            缓存请求参数30分钟
         */
        String cacheKey = CacheKeyUtils.getParamCacheKey(EntityConstant.MQ_MESSAGE_FLOW);
        cacheHelper.cache(cacheKey, messageFlowFormVo, 30, TimeUnit.MINUTES);

        /*
            分页获取消息发送记录
         */
        PageDto<MessageFlowEntity> pageDto = messageFlowService.getPageList(messageFlowFormVo);
        if (pageDto.isEmpty()) {
            return pageDto.rebuild();
        }

        Long totalNum = pageDto.getTotalNum();
        List<MessageFlowEntity> messageFlowList = pageDto.getList();

        BiConsumer<MessageFlowEntity, MessageFlowDto> biConsumer = (messageFlow, messageFlowDto) -> {
            messageFlowDto.setStatusName(MessageStatusEnum.getName(messageFlow.getStatus()));
        };
        List<MessageFlowDto> list = CopyUtils.mapList(messageFlowList, MessageFlowDto.class, biConsumer);

        return new PageDto<>(list, totalNum, messageFlowFormVo.getPage(), messageFlowFormVo.getLimit());
    }

    public MessageFlowEnumDto getMessageFlowListEnum() {
        // 获取请求用户
        Long optUserId = SecurityUtils.getUserId();

        /*
            获取页面参数
         */
        String cacheKey = CacheKeyUtils.getParamCacheKey(EntityConstant.MQ_MESSAGE_FLOW);
        MessageFlowFormVo messageFlowFormVo = cacheHelper.get(cacheKey, MessageFlowFormVo.class);

        MessageFlowEnumDto messageFlowEnumDto = new MessageFlowEnumDto();
        messageFlowEnumDto.setSearchForm(messageFlowFormVo)
                .setExchangeList(MqEnum.getExchangeList())
                .setQueueList(MqEnum.getQueueList())
                .setStatusList(MessageStatusEnum.getList());
        return messageFlowEnumDto;
    }

    public MessageFlowRetryDto retrySendMessage(List<Long> idList) {
        // 获取操作用户
        UserPo userPo = SecurityUtils.getUser();
        Date date = new Date();

        /*
            获取消息发送记录
         */
        List<MessageFlowEntity> messageFlowList = messageFlowService.getList(idList);
        if (messageFlowList.isEmpty()) {
            throw new CzzException(ResultEnum.REFRESH);
        }
        Map<Long, MessageFlowEntity> messageFlowMap = CopyUtils.listToMap(messageFlowList, MessageFlowEntity::getId,
                Function.identity());

        List<String> successList = new ArrayList<>();
        List<String> failList = new ArrayList<>();

        StringBuilder sb = new StringBuilder();
        sb.append(RedisConstant.STRING).append(EntityConstant.MQ_MESSAGE_FLOW).append(RedisConstant.SPLIT).append(SEND);
        int length = sb.length();

        List<MessageFlowEntity> updateMessageFlowList = new ArrayList<>();

        for (Long id : idList) {
            String cacheKey = sb.delete(length, sb.length()).append(id).toString();
            Boolean bool = redisHandler.hasKey(cacheKey);
            if (Boolean.TRUE.equals(bool)) {
                log.info("存在重试消息发送缓存。id={}", id);
                failList.add(id.toString());
                // 从映射中删除
                messageFlowMap.remove(id);
                continue;
            }

            MessageFlowEntity messageFlow = new MessageFlowEntity();
            messageFlow.setId(id)
                    .setStatus(MessageStatusEnum.SUCCESS.getValue())
                    .setUpdateTime(date)
                    .setUpdateUser(userPo.getUsername())
                    .setUpdateUserId(userPo.getUserId());
            updateMessageFlowList.add(messageFlow);
        }

        /*
            修改消息发送记录
         */
        messageFlowService.batchUpdate(updateMessageFlowList);

        for (MessageFlowEntity messageFlow : messageFlowMap.values()) {
            /*
                消息发送
             */
            Object data = JSON.parse(aesService.czzDecrypt(messageFlow.getMessage()));
            log.info("发送消息数据：id={} data={}", messageFlow.getId(), data);
            rabbitHelper.send(messageFlow.getExchange(), messageFlow.getRoutingKey(), data, messageFlow.getId());

            /*
                添加缓存
             */
            String cacheKey = sb.delete(length, sb.length()).append(messageFlow.getId()).toString();
            redisStringHandler.set(cacheKey, StringUtils.EMPTY, 10, TimeUnit.SECONDS);

            // 记录发送结果
            successList.add(messageFlow.getId().toString());
        }

        MessageFlowRetryDto messageFlowRetryDto = new MessageFlowRetryDto();
        messageFlowRetryDto.setSuccessList(successList)
                .setFailList(failList);
        return messageFlowRetryDto;
    }
}
